#ifndef __DEEP_ZOOM_IMAGE_DEBUG_H__
#define __DEEP_ZOOM_IMAGE_DEBUG_H__

//#define LOGGING

#if defined (_DEBUG) || defined (LOGGING)

#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#endif

//#include "runtime.h"
#include "config.h"
#include "DeepZoomImageDLL.h"

using namespace DeepZoomImage;

#if defined (LOGGING) || defined(_DEBUG)

enum RuntimeDebugFlag {
	RUNTIME_DEBUG_ALSA              = 1 << 0,
	RUNTIME_DEBUG_AUDIO             = 1 << 1,
	RUNTIME_DEBUG_PULSE             = 1 << 2,
	RUNTIME_DEBUG_CURL              = 1 << 3,
	RUNTIME_DEBUG_MARKERS           = 1 << 4,
	RUNTIME_DEBUG_MMS               = 1 << 5,
	RUNTIME_DEBUG_MEDIAPLAYER       = 1 << 6,
	RUNTIME_DEBUG_PIPELINE          = 1 << 7,
	RUNTIME_DEBUG_PIPELINE_ERROR    = 1 << 8,
	RUNTIME_DEBUG_CAPTURE           = 1 << 9,
	RUNTIME_DEBUG_FFMPEG            = 1 << 10,
	RUNTIME_DEBUG_SEEK              = 1 << 11,
	RUNTIME_DEBUG_CODECS            = 1 << 12,
	RUNTIME_DEBUG_DP                = 1 << 13,
	RUNTIME_DEBUG_DOWNLOADER        = 1 << 14,
	RUNTIME_DEBUG_FONT              = 1 << 15,
	RUNTIME_DEBUG_LAYOUT            = 1 << 16,
	RUNTIME_DEBUG_MEDIA             = 1 << 17,
	RUNTIME_DEBUG_MEDIAELEMENT      = 1 << 18,
	RUNTIME_DEBUG_BUFFERING         = 1 << 19,
	RUNTIME_DEBUG_ASF               = 1 << 20,
	RUNTIME_DEBUG_PLAYLIST          = 1 << 21,
	RUNTIME_DEBUG_TEXT              = 1 << 22,
	RUNTIME_DEBUG_XAML              = 1 << 23,
	RUNTIME_DEBUG_DEPLOYMENT        = 1 << 24,
	RUNTIME_DEBUG_MSI               = 1 << 25,
	RUNTIME_DEBUG_MP3               = 1 << 26,
	RUNTIME_DEBUG_VALUE             = 1 << 27,
	RUNTIME_DEBUG_DEMUXERS          = 1 << 28,
	RUNTIME_DEBUG_MP4               = 1 << 29,
	RUNTIME_DEBUG_EFFECT            = 1 << 30,
	RUNTIME_DEBUG_OOB               = 1 << 31,
};

enum RuntimeDebugExtraFlag {
	RUNTIME_DEBUG_ALSA_EX           = 1 << 0,
	RUNTIME_DEBUG_AUDIO_EX          = 1 << 1,
	RUNTIME_DEBUG_PULSE_EX          = 1 << 2,
	RUNTIME_DEBUG_MARKERS_EX        = 1 << 3,
	RUNTIME_DEBUG_MEDIAPLAYER_EX    = 1 << 4,
	RUNTIME_DEBUG_MEDIAELEMENT_EX   = 1 << 5,
	RUNTIME_DEBUG_PLAYLIST_EX       = 1 << 6,
	RUNTIME_DEBUG_PIPELINE_EX       = 1 << 7,
	RUNTIME_DEBUG_MMS_EX            = 1 << 8,
	RUNTIME_DEBUG_NPSTREAM          = 1 << 9,
};

struct DebugOption {
	const char *name;
	guint32 flag;
};

extern DEEP_ZOOM_IMAGE_DLL guint32 debug_flags_ex;
extern DEEP_ZOOM_IMAGE_DLL guint32 debug_flags;

const DebugOption * get_debug_options ();
void set_debug_option (guint32 flag, bool set);
bool get_debug_option (guint32 flag);

const DebugOption * get_debug_ex_options ();
void set_debug_ex_option (guint32 flag, bool set);
bool get_debug_ex_option (guint32 flag);

//static int gettimeofday (struct timeval *tv, void *tz)
//{
//	long int l = GetTickCount ();
//
//	tv->tv_sec = l / 1000;
//	tv->tv_usec = (l % 1000) * 1000;
//	return 0;
//}
//
//TimeSpan get_now (void)
//{
//
//	struct timeval tv;
//	TimeSpan res;
//
//	if (gettimeofday (&tv, NULL) == 0) {
//		res = (TimeSpan)(tv.tv_sec * 1000000 + tv.tv_usec) * 10;
//		return res;
//	}
//}

#endif

#define moon_debug(...) printf(__VA_ARGS__)

/*
 * Stack trace (debug) stuff
 */

#ifdef _DEBUG

void print_reftrace (const char * type, const char * typname, int refcount, bool keep);
void dump_frames (void);
void store_reftrace (void *obj, const char *done, guint32 refcount);
void free_reftrace (void *obj);
void show_reftrace (void *obj);

G_BEGIN_DECLS

char* get_reftrace (void);
char* get_stack_trace (void);
void print_stack_trace (void);
void hexdump_addr (void *addr, size_t n);

G_END_DECLS

#else

#define print_stack_trace()
#define print_reftrace(type, typname, refcount, keep)
#define dump_frames()

#endif /* DEBUG */

/*
 * Logging stuff
 */

#ifdef LOGGING

#define LOG_ALSA(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_ALSA)) moon_debug (__VA_ARGS__);
#define LOG_ALSA_EX(...)			if (G_UNLIKELY (debug_flags_ex & RUNTIME_DEBUG_ALSA_EX)) moon_debug (__VA_ARGS__);
#define LOG_AUDIO(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_AUDIO)) moon_debug (__VA_ARGS__);
#define LOG_AUDIO_EX(...)			if (G_UNLIKELY (debug_flags_ex & RUNTIME_DEBUG_AUDIO_EX)) moon_debug (__VA_ARGS__);
#define LOG_PULSE(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_PULSE)) moon_debug (__VA_ARGS__);
#define LOG_PULSE_EX(...)			if (G_UNLIKELY (debug_flags_ex & RUNTIME_DEBUG_PULSE_EX)) moon_debug (__VA_ARGS__);
#define LOG_CURL(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_CURL)) moon_debug (__VA_ARGS__);
#define LOG_MARKERS(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_MARKERS)) moon_debug (__VA_ARGS__);
#define LOG_MARKERS_EX(...)			if (G_UNLIKELY (debug_flags_ex & RUNTIME_DEBUG_MARKERS_EX)) moon_debug (__VA_ARGS__);
#define LOG_MMS(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_MMS)) moon_debug (__VA_ARGS__);
#define LOG_MMS_EX(...)             if (G_UNLIKELY (debug_flags_ex & RUNTIME_DEBUG_MMS_EX)) moon_debug (__VA_ARGS__);
#define LOG_MEDIAPLAYER(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_MEDIAPLAYER)) moon_debug (__VA_ARGS__);
#define LOG_MEDIAPLAYER_EX(...)			if (G_UNLIKELY (debug_flags_ex & RUNTIME_DEBUG_MEDIAPLAYER_EX)) moon_debug (__VA_ARGS__);
#define LOG_PIPELINE(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_PIPELINE)) moon_debug (__VA_ARGS__);
#define LOG_PIPELINE_EX(...)		if (G_UNLIKELY (debug_flags_ex & RUNTIME_DEBUG_PIPELINE_EX)) moon_debug (__VA_ARGS__);
#define LOG_PIPELINE_ERROR(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_PIPELINE_ERROR)) moon_debug (__VA_ARGS__);
#define LOG_PIPELINE_ERROR_CONDITIONAL(x, ...) if (G_UNLIKELY (x && debug_flags & PIPELINE_ERROR)) moon_debug (__VA_ARGS__);
#define LOG_FRAMEREADERLOOP(...)		if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_FRAMEREADERLOOP)) moon_debug (__VA_ARGS__);
#define LOG_FFMPEG(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_FFMPEG)) moon_debug(__VA_ARGS__);
#define LOG_CODECS(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_CODECS)) moon_debug (__VA_ARGS__);
#define LOG_DP(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_DP)) moon_debug (__VA_ARGS__);
#define LOG_DOWNLOADER(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_DOWNLOADER)) moon_debug (__VA_ARGS__);
#define LOG_FONT(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_FONT)) moon_debug (__VA_ARGS__);
#define LOG_LAYOUT(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_LAYOUT)) moon_debug (__VA_ARGS__);
#define LOG_MEDIA(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_MEDIA)) moon_debug (__VA_ARGS__);
#define LOG_MEDIAELEMENT(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_MEDIAELEMENT)) moon_debug (__VA_ARGS__);
#define LOG_MEDIAELEMENT_EX(...)		if (G_UNLIKELY (debug_flags_ex & RUNTIME_DEBUG_MEDIAELEMENT_EX)) moon_debug (__VA_ARGS__);
#define LOG_MSI(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_MSI)) moon_debug (__VA_ARGS__);
#define LOG_BUFFERING(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_BUFFERING)) moon_debug (__VA_ARGS__);
#define LOG_PLAYLIST(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_PLAYLIST)) moon_debug (__VA_ARGS__);
#define LOG_TEXT(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_TEXT)) moon_debug (__VA_ARGS__);
#define LOG_XAML(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_XAML)) moon_debug (__VA_ARGS__);
#define LOG_DEPLOYMENT(...)		if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_DEPLOYMENT)) moon_debug (__VA_ARGS__);
#define LOG_MP3(...)				if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_MP3)) moon_debug (__VA_ARGS__);
#define LOG_ASF(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_ASF)) moon_debug (__VA_ARGS__);
#define LOG_VALUE(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_VALUE)) moon_debug (__VA_ARGS__);
#define LOG_DEMUXERS(...)		if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_DEMUXERS)) moon_debug (__VA_ARGS__);
#define LOG_MP4(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_MP4)) moon_debug (__VA_ARGS__);
#define LOG_EFFECT(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_EFFECT)) moon_debug (__VA_ARGS__);
#define LOG_OOB(...)			if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_OOB)) moon_debug (__VA_ARGS__);
#define LOG_CUSTOM(x,...)		if (G_UNLIKELY (debug_flags & (x))) moon_debug (__VA_ARGS__);
#define LOG_CAPTURE(...)        if (G_UNLIKELY (debug_flags & RUNTIME_DEBUG_CAPTURE)) moon_debug (__VA_ARGS__);
#define LOG_NPSTREAM(...)       if (G_UNLIKELY (debug_flags_ex & RUNTIME_DEBUG_NPSTREAM)) moon_debug (__VA_ARGS__);

#else

#define LOG_ALSA(...)
#define LOG_ALSA_EX(...)
#define LOG_AUDIO(...)
#define LOG_AUDIO_EX(...)
#define LOG_PULSE(...)
#define LOG_PULSE_EX(...)
#define LOG_CURL(...)
#define LOG_MARKERS(...)
#define LOG_MARKERS_EX(...)
#define LOG_MMS(...)
#define LOG_MMS_EX(...)
#define LOG_MEDIAPLAYER(...)
#define LOG_MEDIAPLAYER_EX(...)
#define LOG_PIPELINE(...)
#define LOG_PIPELINE_EX(...)
#define LOG_PIPELINE_ERROR(...)
#define LOG_PIPELINE_ERROR_CONDITIONAL(x, ...)
#define LOG_FRAMEREADERLOOP(...)
#define LOG_FFMPEG(...)
#define LOG_CODECS(...)
#define LOG_DP(...)
#define LOG_DOWNLOADER(...)
#define LOG_FONT(...)
#define LOG_LAYOUT(...)
#define LOG_MEDIA(...)
#define LOG_MEDIAELEMENT(...)
#define LOG_MEDIAELEMENT_EX(...)
#define LOG_MSI(...)
#define LOG_BUFFERING(...)
#define LOG_PLAYLIST(...)
#define LOG_TEXT(...)
#define LOG_XAML(...)
#define LOG_DEPLOYMENT(...)
#define LOG_MP3(...)
#define LOG_ASF(...)
#define LOG_VALUE(...)
#define LOG_DEMUXERS(...)
#define LOG_MP4(...)
#define LOG_EFFECT(...)
#define LOG_OOB(...)
#define LOG_CUSTOM(...)
#define LOG_CAPTURE(...)
#define LOG_NPSTREAM(...)

#endif /* LOGGING */

#if SANITY && defined (_DEBUG)
G_BEGIN_DECLS
void moonlight_install_signal_handlers ();
G_END_DECLS
#else
#define moonlight_install_signal_handlers() 
#endif /* SANITY */

#endif /* __DEEP_ZOOM_IMAGE_DEBUG_H__ */

